package cn.edu.usst.cs.ori;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class PiSequenceFinder {
    private static final String TARGET = "6939937510";
    private static final int TARGET_OCCURRENCE = 99;
    private static final int BUFFER_SIZE = 1000;
    private static final int QUEUE_CAPACITY = 10;

    private static final ArrayBlockingQueue<String> piQueue = new ArrayBlockingQueue<>(QUEUE_CAPACITY);
    private static final AtomicInteger occurrenceCounter = new AtomicInteger(0);
    private static volatile boolean found = false;

    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(2);

        // Start Pi calculation thread
        executor.execute(PiSequenceFinder::calculatePiDigits);

        // Start sequence search thread
        executor.execute(PiSequenceFinder::searchTargetSequence);

        executor.shutdown();
    }

    private static void calculatePiDigits() {
        int position = 0;
//        PiSegmentCalculator segmentCalculator = new PiSegmentCalculator();
        while (!found) {
            String piSegment = PiSegmentCalculator.calculatePiSegment(position, BUFFER_SIZE);
            try {
                piQueue.put(piSegment);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
            position += BUFFER_SIZE;
        }
    }

    private static void searchTargetSequence() {
        int currentIndex = 0;
        StringBuilder piDigits = new StringBuilder();

        while (!found) {
            try {
                String piSegment = piQueue.take();
                piDigits.append(piSegment);

                int index;
                while ((index = piDigits.indexOf(TARGET, currentIndex)) != -1) {
                    currentIndex = index + 1;
                    if (occurrenceCounter.incrementAndGet() == TARGET_OCCURRENCE) {
                        System.out.println("The " + TARGET_OCCURRENCE + "th occurrence of the sequence " + TARGET +
                                " is at position: " + (index));
                        found = true;
                        return;
                    }
                }

                // Remove used portion from buffer to save memory
                if (piDigits.length() > BUFFER_SIZE) {
                    piDigits.delete(0, piDigits.length() - BUFFER_SIZE);
                    currentIndex = Math.max(0, currentIndex - BUFFER_SIZE);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
        }
    }

    // Mock function for Pi segment calculation (for demonstration purposes)
    private static String calculatePiSegment(int start, int length) {
        // In a real implementation, replace with BBP or a precise Pi calculation formula
        return "mock_pi_digits";  // Replace with actual calculation for real use
    }
}
